package it.uniroma2.structure;

import groovy.xml.QName;

import java.io.Serializable;
import java.util.List;
import java.util.Vector;

import com.predic8.schema.ComplexType;
import com.predic8.schema.Element;
import com.predic8.schema.Schema;
import com.predic8.schema.Sequence;
import com.predic8.schema.TypeDefinition;
import com.predic8.wsdl.Definitions;
import com.predic8.wsdl.Message;
import com.predic8.wsdl.Operation;
import com.predic8.wsdl.Part;
import com.predic8.wsdl.PortType;
import com.predic8.wsdl.Service;
import com.predic8.wsdl.WSDLParser;


public class Wsdl_Service implements Serializable{
	private String pathWSDL;
	
	
	public Wsdl_Service(String path) {
		this.pathWSDL = path;
	}
	

	public String getTargetNamespace() {
		WSDLParser parser = new WSDLParser();
		Definitions definitions = parser.parse(pathWSDL);
		return definitions.getTargetNamespace();
	}


	public Message getMessageInput(String operationName) {
		WSDLParser parser = new WSDLParser();
		Definitions definitions = parser.parse(pathWSDL);
		List<Operation> listOp = definitions.getOperations();
		
		for(Operation tempOp : listOp){
			if(tempOp.getName().equals(operationName)){
				return tempOp.getInput().getMessage();
			}
		}
		
		return null;
	}


	public Message getMessageOutput(String operationName) {
		WSDLParser parser = new WSDLParser();
		Definitions definitions = parser.parse(pathWSDL);
		List<Operation> listOp = definitions.getOperations();
		
		for(Operation tempOp : listOp){
			if(tempOp.getName().equals(operationName)){
				return tempOp.getOutput().getMessage();
			}
		}
		
		return null;
	}


	public String getOperation() {
		WSDLParser parser = new WSDLParser();
		Definitions definitions = parser.parse(pathWSDL);
		return definitions.getOperations().get(0).getName();
	}


	public String getPortType(String operationName) {
		WSDLParser parser = new WSDLParser();
		Definitions definitions = parser.parse(pathWSDL);
		List<PortType> ports = definitions.getPortTypes();
		for(PortType temp : ports){
			List<Operation> ops = temp.getOperations();
			for(Operation tempOp : ops){
				if(tempOp.getName().equals(operationName)){
					return temp.getName();
				}
			}
			
		}
		return null;
	}
	
	public Vector<String> getElementIn(String operationName){
		Vector<String> vec = new Vector<String>();
		Message msg = this.getMessageInput(operationName);
		List<Part> listPart = msg.getParts();
		
		WSDLParser parser = new WSDLParser();
		Definitions definitions = parser.parse(pathWSDL);
		for(Part tempP : listPart){
			String tmp = tempP.getElement();
			Element el = definitions.getElement(tmp);
			ComplexType ct = (ComplexType) el.getEmbeddedType();
			Sequence seq = ct.getSequence();
			List<Element> listEl = seq.getElements();
			for(Element temElement : listEl){
				vec.addElement(temElement.getName());
			}
		}
		return vec;
	}
	
	
	public Vector<String> getElementOut(String operationName){
		Vector<String> vec = new Vector<String>();
		Message msg = this.getMessageOutput(operationName);
		List<Part> listPart = msg.getParts();
		WSDLParser parser = new WSDLParser();
		Definitions definitions = parser.parse(pathWSDL);
		for(Part tempP : listPart){
			String tmp = tempP.getElement();
			
			Element el = definitions.getElement(tmp);
			ComplexType ct = (ComplexType) el.getEmbeddedType();
			Sequence seq = ct.getSequence();
			List<Element> listEl = seq.getElements();
			for(Element temElement : listEl){
				vec.addElement(temElement.getName());
			}
		}
		return vec;
	}


	public String getService() {
		String service = "";
		WSDLParser parser = new WSDLParser();
		Definitions definitions = parser.parse(pathWSDL);
		List<Service> listService = definitions.getServices();
		service = listService.get(0).getName();
		
		return service;
	}
	
	
	public String getElements(String message, String prefix) {
		String output = "";
		WSDLParser parser = new WSDLParser();
		Definitions definitions = parser.parse(pathWSDL);
		Message msg = definitions.getMessage(message);
		Element elementRoot = definitions.getSchemas().get(0).getElement(msg.getParts().get(0).getElement());
		output = output + "<" + prefix + ":" + elementRoot.getName() + " xmlns:impl=\"" + definitions.getTargetNamespace()
				+ "\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";
				
		if(elementRoot.getEmbeddedType() instanceof ComplexType){
			ComplexType ct = (ComplexType) elementRoot.getEmbeddedType();
			
			List<Element> list = ct.getSequence().getElements();
			for(Element temp : list){
				output = output + this.getSubElement(temp, prefix);
			}
		}
		
		output = output + "</" + prefix + ":" + elementRoot.getName() + ">";
		return output;
	}
	
	
	private String getSubElement(Element element, String prefix){
		String result = "<" + prefix + ":" + element.getName() + ">";
		TypeDefinition td = element.getEmbeddedType();
		
		if(td != null){
			if(td instanceof ComplexType){
				Sequence seq = ((ComplexType)td).getSequence();
				List<Element> list = seq.getElements();
				for(Element temp : list){
					result = result + this.getSubElement(temp, prefix);
				}
				result = result + "</" + prefix + ":" + element.getName() + ">";
			}
		}else if(element.getType() != null){
			QName type = element.getType();
			if(type.getPrefix().equals("xsd")){
				result = result + prefix + ":" + element.getName();
				result = result + "</" + prefix + ":" + element.getName() + ">";
			}else{
				WSDLParser parser = new WSDLParser();
				Definitions definitions = parser.parse(pathWSDL);
				System.out.println(definitions.getSchemas().size());
				for(Schema schema : definitions.getSchemas()){
					ComplexType el = schema.getComplexType(type.getLocalPart());
					if(el != null){
						Sequence seq = el.getSequence();
						List<Element> list = seq.getElements();
						for(Element temp : list){
							result = result + this.getSubElement(temp, prefix);
						}
						result = result + "</" + prefix + ":" + element.getName() + ">";
					}
				}
				
				}
		}
		
		return result;
	}


	public Element getElementByName(String name) {
		WSDLParser parser = new WSDLParser();
		Definitions definitions = parser.parse(pathWSDL);
		return definitions.getElement(name);
	}
}
